SageMaker Unified Studio を使うときには VPC エンドポイントに注意しよう

SageMaker Unified Studio を使うときには VPC エンドポイントに注意しよう

Clock Icon2024.12.18

こんにちは、森田です。

先日から SageMaker Unified Studio を触っているのですが、意図せずコストが発生していました。

https://dev.classmethod.jp/articles/sagemaker-unified-studio

さきにまとめ

  • AWS提供の CloudFormation テンプレートでは、81個のVPCエンドポイントの作成が含まれる
  • VPCエンドポイントを利用しない場合は、 CloudFormation テンプレートで useVpcEndpointsfalseを指定する

どういうことか

SageMaker Unified Studio を利用する際には、用途によっては、VPCが必要となります。

特にクイックセットアップを利用する際には、以下のようにVPCの作成が求められます。

スクリーンショット 2024-12-18 22.47.44.png

このVPCの作成を押すと、AWS 提供のCloudFormation テンプレートを使ったスタックの作成ページが開きます。

AWS 提供のCloudFormation テンプレートでは、VPC、サブネット、NAT ゲートウェイなどのリソース作成が行われますが、その中にVPCエンドポイントが含まれています。

VPCエンドポイント2~3個程度であれば、良かったのですが、27種類のサービス3AZで合計81個のVPCエンドポイントが作成されます。

スクリーンショット_2024-12-18_23_07_00.png

私はこの状態に気づかず、意図せず、コストがかかってしました。

どうすればよかったのか

CloudFormation テンプレートをしっかりと確認すべきでした。

AWS 提供の CloudFormation テンプレートでしたので、ざっくりとしか確認していませんでした。

YAMLテンプレートでも人の目でパッと確認することが難しいなら、生成AIを使って確認するのも一つの手でした。。

プロンプト例(Claude 3.5 Sonnet v2)

以下のCloudFormationテンプレートを実行すると、利用費が著しく発生するリソースはありますか?
<CloudFormation テンプレート>
回答結果
回答結果
このCloudFormationテンプレートでは、主に以下のリソースで利用料金が発生する可能性があります:

1. **VPCエンドポイント (AWS::EC2::VPCEndpoint)**
   - インターフェイスVPCエンドポイント(Interface endpoints)は時間単位で課金されます
   - このテンプレートでは多数のVPCエンドポイントが作成されており(Glue, EMR, SageMaker, Athena, Bedrock等)、これらは累積的にコストが発生します
   - 料金は地域によって異なりますが、例えば米国東部(バージニア北部)では1つのエンドポイントあたり約$0.01/時間

2. **NAT Gateway (暗示的に必要)**
   - プライベートサブネットからインターネットへのアウトバウンド通信に必要
   - 時間単位の料金とデータ処理料金の両方が発生
   - 比較的高額な料金が発生する可能性があるリソース

3. **Elastic IP (AWS::EC2::EIP)**
   - EC2インスタンスにアタッチされていない場合、少額の料金が発生

これらの中で、特に注意が必要なのは:

1. **VPCエンドポイント**: 数が多いため、合計のコストが大きくなる可能性があります
2. **NAT Gateway**: データ転送量によっては大きなコストが発生する可能性があります

コスト最適化のためには:
- 本当に必要なVPCエンドポイントのみを作成する
- 使用していない時はリソースを削除する
- データ転送量を監視し、必要に応じて最適化を行う

などの対策を検討することをお勧めします。

現在はテンプレートが変更になっている

本日(2024/12/18)この記事を執筆するために、再度テンプレートを確認したところ、VPCエンドポイントの選択ができるようになっていました。

スクリーンショット_2024-12-18_23_20_50.png

2024/12/18時点のテンプレート
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  useVpcEndpoints:
    Type: String
    AllowedValues:
      - true
      - false
    Default: false
    Description: This controls whether VPC endpoints are created or not.

Mappings:
  # found with describe-vpc-endpoint-services --service-names com.amazonaws.<region>.redshift-serverless
  # AZ IDs are fetched with aws ec2 describe-availability-zones --region <region> --query 'AvailabilityZones[*].[ZoneName, ZoneId]' --output text
  AvailabilityZonesId:
    eu-west-1:
      AZ1: euw1-az1
      AZ2: euw1-az2
      AZ3: euw1-az3
      AZ4: ""
    us-east-1:
      AZ1: use1-az1
      AZ2: use1-az2
      AZ3: use1-az4
      AZ4: use1-az6
    us-west-2:
      AZ1: usw2-az1
      AZ2: usw2-az2
      AZ3: usw2-az3
      AZ4: ""
    us-east-2:
      AZ1: use2-az1
      AZ2: use2-az2
      AZ3: use2-az3
      AZ4: ""
    eu-central-1:
      AZ1: euc1-az2
      AZ2: euc1-az3
      AZ3: euc1-az1
      AZ4: ""
    sa-east-1:
      AZ1: sae1-az1
      AZ2: sae1-az2
      AZ3: sae1-az3
      AZ4: ""
    ap-northeast-2:
      AZ1: apne2-az1
      AZ2: apne2-az2
      AZ3: apne2-az3
      AZ4: ""
    eu-west-2:
      AZ1: euw2-az2
      AZ2: euw2-az3
      AZ3: euw2-az1
      AZ4: ""
    ap-northeast-1:
      AZ1: apne1-az4
      AZ2: apne1-az1
      AZ3: apne1-az2
      AZ4: ""
    ap-southeast-1:
      AZ1: apse1-az2
      AZ2: apse1-az1
      AZ3: apse1-az3
      AZ4: ""
    ap-southeast-2:
      AZ1: apse2-az3
      AZ2: apse2-az1
      AZ3: apse2-az2
      AZ4: ""
    ca-central-1:
      AZ1: cac1-az1
      AZ2: cac1-az2
      AZ3: cac1-az4
      AZ4: ""

Conditions:
  useVpcEndpoints: !Equals [!Ref useVpcEndpoints, "true"]

  codeWhispererEnabledRegion: !Equals [!Ref "AWS::Region", 'us-east-1']
  qEnabledRegion: !Equals [!Ref "AWS::Region", 'us-east-1']
  isUSEast1: !Equals [!Ref "AWS::Region", 'us-east-1']
  isSAEast1: !Equals [!Ref "AWS::Region", 'sa-east-1']
  isCACentral1: !Equals [!Ref "AWS::Region", 'ca-central-1']

  hasAZ1ForRegion: !Not [!Equals [!FindInMap [AvailabilityZonesId, !Ref "AWS::Region", AZ1], ""]]
  hasAZ2ForRegion: !Not [!Equals [!FindInMap [AvailabilityZonesId, !Ref "AWS::Region", AZ2], ""]]
  hasAZ3ForRegion: !Not [!Equals [!FindInMap [AvailabilityZonesId, !Ref "AWS::Region", AZ3], ""]]
  hasAZ4ForRegion: !Not [!Equals [!FindInMap [AvailabilityZonesId, !Ref "AWS::Region", AZ4], ""]]

  createVPCEWithTwoSubnets: !And [!Condition useVpcEndpoints, !Condition hasAZ1ForRegion, !Condition hasAZ2ForRegion, !Not [!Condition hasAZ3ForRegion]]
  createVPCEWithThreeSubnets: !And [!Condition useVpcEndpoints, !Condition hasAZ1ForRegion, !Condition hasAZ2ForRegion, !Condition hasAZ3ForRegion]

  createVPCEWithTwoSubnetsRedshiftServerless: !And [!Condition useVpcEndpoints, !Condition hasAZ1ForRegion, !Condition hasAZ2ForRegion, !Not [!Condition hasAZ3ForRegion]]
  createVPCEWithThreeSubnetsRedshiftServerlessNotUSEast1: !And [!Condition useVpcEndpoints, !Condition hasAZ1ForRegion, !Condition hasAZ2ForRegion, !Condition hasAZ3ForRegion, !Not [!Condition isUSEast1]]
  createVPCEWithThreeSubnetsRedshiftServerlessUSEast1: !And [!Condition useVpcEndpoints, !Condition hasAZ1ForRegion, !Condition hasAZ2ForRegion, !Condition hasAZ4ForRegion, !Condition isUSEast1]

  createVPCEWithTwoSubnetsCodeWhisperer: !And [!Condition useVpcEndpoints, !Condition codeWhispererEnabledRegion, !Condition createVPCEWithTwoSubnets]
  createVPCEWithThreeSubnetsCodeWhisperer: !And [!Condition useVpcEndpoints, !Condition codeWhispererEnabledRegion, !Condition createVPCEWithThreeSubnets]

  createVPCEWithTwoSubnetsQ: !And [!Condition useVpcEndpoints, !Condition qEnabledRegion, !Condition createVPCEWithTwoSubnets]
  createVPCEWithThreeSubnetsQ: !And [!Condition useVpcEndpoints, !Condition qEnabledRegion, !Condition createVPCEWithThreeSubnets]

  createVPCEWithTwoSubnetsCodeCommit: !And [!Condition useVpcEndpoints, !Condition isSAEast1]
  createVPCEWithThreeSubnetsCodeCommit: !And [!Condition useVpcEndpoints, !Not [!Condition isSAEast1]]

  createVPCEWithTwoSubnetsGitCodeCommit: !And [!Condition useVpcEndpoints, !Condition isSAEast1]
  createVPCEWithThreeSubnetsGitCodeCommit: !And [!Condition useVpcEndpoints, !Not [!Condition isSAEast1]]

  createVPCEWithTwoSubnetsEMR: !And [!Condition useVpcEndpoints, !Condition isCACentral1]
  createVPCEWithThreeSubnetsEMR: !And [!Condition useVpcEndpoints, !Not [!Condition isCACentral1]]

  createVPCEWithTwoSubnetsRedshift: !And [!Condition useVpcEndpoints, !Condition isCACentral1]
  createVPCEWithThreeSubnetsRedshift: !And [!Condition useVpcEndpoints, !Not [!Condition isCACentral1]]

Resources:
  SageMakerUnifiedStudioVpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: "10.38.0.0/16"
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: CreatedForUseWithSageMakerUnifiedStudio
          Value: true
        - Key: Name
          Value: 'SageMakerUnifiedStudioVPC'
        - Key: for-use-with-amazon-emr-managed-policies
          Value: true

  SageMakerUnifiedStudioSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for the VPC-endpoints.
      GroupName: 'sagemaker-unified-studio-vpc-endpoint'
      SecurityGroupEgress:
        - Description: Allows outbound HTTPS access to any IPv4 address
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
      SecurityGroupIngress:
        - Description: Allows inbound HTTPS access for traffic from VPC
          IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 10.38.0.0/16
      Tags:
        - Key: CreatedForUseWithSageMakerUnifiedStudio
          Value: true
      VpcId: !Ref SageMakerUnifiedStudioVpc

  SageMakerUnifiedStudioPublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: "10.38.224.0/21"
      VpcId: !Ref SageMakerUnifiedStudioVpc
      Tags:
        - Key: CreatedForUseWithSageMakerUnifiedStudio
          Value: true
        - Key: Name
          Value: 'SageMakerUnifiedStudioPublicSubnet'
        - Key: for-use-with-amazon-emr-managed-policies
          Value: true

  PublicRouteTableIGWRoute:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref SageMakerUnifiedStudioVpcInternetGateway
      RouteTableId: !Ref PublicRouteTable

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref SageMakerUnifiedStudioVpc

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref SageMakerUnifiedStudioPublicSubnet

  SageMakerUnifiedStudioPrivateSubnet1:
    Condition: hasAZ1ForRegion
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZoneId: !FindInMap [AvailabilityZonesId, !Ref "AWS::Region", AZ1]
      CidrBlock: "10.38.192.0/21"
      VpcId: !Ref SageMakerUnifiedStudioVpc
      Tags:
        - Key: CreatedForUseWithSageMakerUnifiedStudio
          Value: true
        - Key: Name
          Value: 'SageMakerUnifiedStudioPrivateSubnet1'
        - Key: for-use-with-amazon-emr-managed-policies
          Value: true

  SageMakerUnifiedStudioPrivateSubnet2:
    Condition: hasAZ2ForRegion
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZoneId: !FindInMap [AvailabilityZonesId, !Ref "AWS::Region", AZ2]
      CidrBlock: "10.38.200.0/21"
      VpcId: !Ref SageMakerUnifiedStudioVpc
      Tags:
        - Key: CreatedForUseWithSageMakerUnifiedStudio
          Value: true
        - Key: Name
          Value: 'SageMakerUnifiedStudioPrivateSubnet2'
        - Key: for-use-with-amazon-emr-managed-policies
          Value: true

  SageMakerUnifiedStudioPrivateSubnet3:
    Condition: hasAZ3ForRegion
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZoneId: !FindInMap [AvailabilityZonesId, !Ref "AWS::Region", AZ3]
      CidrBlock: "10.38.208.0/21"
      VpcId: !Ref SageMakerUnifiedStudioVpc
      Tags:
        - Key: CreatedForUseWithSageMakerUnifiedStudio
          Value: true
        - Key: Name
          Value: 'SageMakerUnifiedStudioPrivateSubnet3'
        - Key: for-use-with-amazon-emr-managed-policies
          Value: true

  SageMakerUnifiedStudioPrivateSubnet4:
    Condition: hasAZ4ForRegion
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZoneId: !FindInMap [AvailabilityZonesId, !Ref "AWS::Region", AZ4]
      CidrBlock: "10.38.216.0/21"
      VpcId: !Ref SageMakerUnifiedStudioVpc
      Tags:
        - Key: CreatedForUseWithSageMakerUnifiedStudio
          Value: true
        - Key: Name
          Value: 'SageMakerUnifiedStudioPrivateSubnet4'
        - Key: for-use-with-amazon-emr-managed-policies
          Value: true

  SageMakerUnifiedStudioEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  SageMakerUnifiedStudioVpcInternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties: {}
  SageMakerUnifiedStudioVpcInternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref SageMakerUnifiedStudioVpcInternetGateway
      VpcId: !Ref SageMakerUnifiedStudioVpc

  SageMakerUnifiedStudioPublicSubnetNATGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt SageMakerUnifiedStudioEIP.AllocationId
      SubnetId: !Ref SageMakerUnifiedStudioPublicSubnet

  SageMakerUnifiedStudioRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref SageMakerUnifiedStudioVpc

  PrivateRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref SageMakerUnifiedStudioRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref SageMakerUnifiedStudioPublicSubnetNATGateway

  PrivateSubnetRouteTableAssociation1:
    Condition: hasAZ1ForRegion
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref SageMakerUnifiedStudioRouteTable
      SubnetId: !Ref SageMakerUnifiedStudioPrivateSubnet1

  PrivateSubnetRouteTableAssociation2:
    Condition: hasAZ2ForRegion
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref SageMakerUnifiedStudioRouteTable
      SubnetId: !Ref SageMakerUnifiedStudioPrivateSubnet2

  PrivateSubnetRouteTableAssociation3:
    Condition: hasAZ3ForRegion
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref SageMakerUnifiedStudioRouteTable
      SubnetId: !Ref SageMakerUnifiedStudioPrivateSubnet3

  PrivateSubnetRouteTableAssociation4:
    Condition: hasAZ4ForRegion
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref SageMakerUnifiedStudioRouteTable
      SubnetId: !Ref SageMakerUnifiedStudioPrivateSubnet4

  ############################################################
  # Glue VPC-E
  ############################################################
  SageMakerUnifiedStudioGlueVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.glue'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioGlueVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.glue'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # EMR Serverless VPC-E
  ############################################################
  SageMakerUnifiedStudioEMRServerlessVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.emr-serverless'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioEMRServerlessVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.emr-serverless'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # EMR on EKS VPC-E
  ############################################################
  SageMakerUnifiedStudioEMRonEKSVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.emr-containers'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioEMRonEKSVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.emr-containers'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # CodeCommit VPC-E
  ############################################################
  SageMakerUnifiedStudioCodeCommitVpcEndpointA:
    Condition: createVPCEWithTwoSubnetsCodeCommit
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.codecommit'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  SageMakerUnifiedStudioCodeCommitVpcEndpointB:
    Condition: createVPCEWithThreeSubnetsCodeCommit
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.codecommit'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Git CodeCommit VPC-E
  ############################################################
  SageMakerUnifiedStudioGitCodeCommitVpcEndpointA:
    Condition: createVPCEWithTwoSubnetsGitCodeCommit
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.git-codecommit'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  SageMakerUnifiedStudioGitCodeCommitVpcEndpointB:
    Condition: createVPCEWithThreeSubnetsGitCodeCommit
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.git-codecommit'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # STS VPC-E
  ############################################################      
  SageMakerUnifiedStudioStsVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.sts'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioStsVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.sts'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # S3 VPC-E
  ############################################################
  SageMakerUnifiedStudioS3VpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
      VpcEndpointType: Gateway
      VpcId: !Ref SageMakerUnifiedStudioVpc
      RouteTableIds:
        - !Ref SageMakerUnifiedStudioRouteTable

  ############################################################
  # SageMaker API VPC-E
  ############################################################
  SageMakerUnifiedStudioSageMakerApiVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.sagemaker.api'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioSageMakerApiVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.sagemaker.api'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # SageMaker Runtime VPC-E
  ############################################################
  SageMakerUnifiedStudioSageMakerRuntimeVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.sagemaker.runtime'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioSageMakerRuntimeVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.sagemaker.runtime'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Code Connections API VPC-E
  ############################################################
  SageMakerUnifiedStudioCodeConnectionVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.codeconnections.api'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioCodeConnectionVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.codeconnections.api'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Codestar Connections API VPC-E
  ############################################################
  SageMakerUnifiedStudioCodeStarVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.codestar-connections.api'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioCodeStarVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.codestar-connections.api'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Redshift Serverless VPC-E
  ############################################################
  SageMakerUnifiedStudioRedshiftServerlessVpcEndpointA:
    Condition: createVPCEWithTwoSubnetsRedshiftServerless
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.redshift-serverless'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioRedshiftServerlessVpcEndpointB:
    Condition: createVPCEWithThreeSubnetsRedshiftServerlessNotUSEast1
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.redshift-serverless'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  SageMakerUnifiedStudioRedshiftServerlessVpcEndpointC:
    Condition: createVPCEWithThreeSubnetsRedshiftServerlessUSEast1
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.redshift-serverless'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet4

  ############################################################
  # Redshift VPC-E
  ############################################################
  SageMakerUnifiedStudioRedshiftVpcEndpointA:
    Condition: createVPCEWithTwoSubnetsRedshift
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.redshift'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioRedshiftVpcEndpointB:
    Condition: createVPCEWithThreeSubnetsRedshift
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.redshift'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Redshift Data VPC-E
  ############################################################
  SageMakerUnifiedStudioRedshiftDataVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.redshift-data'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioRedshiftDataVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.redshift-data'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # DataZone VPC-E
  ############################################################
  SageMakerUnifiedStudioDataZoneVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.datazone'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioDataZoneVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.datazone'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Secrets Manager VPC-E
  ############################################################
  SageMakerUnifiedStudioSecretsManagerVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.secretsmanager'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioSecretsManagerVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.secretsmanager'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # SSM VPC-E
  ############################################################
  SageMakerUnifiedStudioSSMVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioSSMVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # EC2 Messages VPC-E
  ############################################################
  SageMakerUnifiedStudioEC2MessagesVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ec2messages'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioEC2MessagesVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ec2messages'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # KMS VPC-E
  ############################################################
  SageMakerUnifiedStudioKMSVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.kms'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioKMSVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.kms'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # CloudWatch Logs VPC-E
  ############################################################
  SageMakerUnifiedStudioLogsVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.logs'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioLogsVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.logs'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # SSM Messages VPC-E
  ############################################################
  SageMakerUnifiedStudioSSMMessagesVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssmmessages'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioSSMMessagesVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssmmessages'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Athena VPC-E
  ############################################################
  SageMakerUnifiedStudioAthenaVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.athena'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioAthenaVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.athena'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # EMR VPC-E
  ############################################################
  SageMakerUnifiedStudioEMRVpcEndpointA:
    Condition: createVPCEWithTwoSubnetsEMR
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.elasticmapreduce'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioEMRVpcEndpointB:
    Condition: createVPCEWithThreeSubnetsEMR
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.elasticmapreduce'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # EC2 VPC-E
  ############################################################
  SageMakerUnifiedStudioEC2VpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ec2'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioEC2VpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ec2'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Code Whisperer VPC-E
  ############################################################
  SageMakerUnifiedStudioCodeWhispererVpcEndpointA:
    Condition: createVPCEWithTwoSubnetsCodeWhisperer
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.codewhisperer'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioCodeWhispererVpcEndpointB:
    Condition: createVPCEWithThreeSubnetsCodeWhisperer
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.codewhisperer'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Q VPC-E
  ############################################################
  SageMakerUnifiedStudioQVpcEndpointA:
    Condition: createVPCEWithTwoSubnetsQ
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.q'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioQVpcEndpointB:
    Condition: createVPCEWithThreeSubnetsQ
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.q'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Bedrock VPC-E
  ############################################################
  SageMakerUnifiedStudioBedrockVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.bedrock'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioBedrockVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.bedrock'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Bedrock Runtime VPC-E
  ############################################################
  SageMakerUnifiedStudioBedrockRuntimeVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.bedrock-runtime'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioBedrockRuntimeVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.bedrock-runtime'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Bedrock Agent VPC-E
  ############################################################
  SageMakerUnifiedStudioBedrockAgentVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.bedrock-agent'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioBedrockAgentVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.bedrock-agent'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

  ############################################################
  # Bedrock Agent Runtime VPC-E
  ############################################################
  SageMakerUnifiedStudioBedrockAgentRuntimeVpcEndpointA:
    Condition: createVPCEWithTwoSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.bedrock-agent-runtime'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2

  SageMakerUnifiedStudioBedrockAgentRuntimeVpcEndpointB:
    Condition: createVPCEWithThreeSubnets
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.bedrock-agent-runtime'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      VpcId: !Ref SageMakerUnifiedStudioVpc
      SecurityGroupIds:
        - !Ref SageMakerUnifiedStudioSecurityGroup
      SubnetIds:
        - !Ref SageMakerUnifiedStudioPrivateSubnet1
        - !Ref SageMakerUnifiedStudioPrivateSubnet2
        - !Ref SageMakerUnifiedStudioPrivateSubnet3

このテンプレートであれば、デフォルトでVPCエンドポイントは作成しないようになっているため安全ですね。(NAT Gatewayは引き続き作成されるので、ご注意ください。)

さいごに

利用費アラートを設定しているため、早めに気づけたため、少額の利用費増加で済みました。

利用費アラートは、やっぱり大事ですね。

https://dev.classmethod.jp/articles/cost_over_kaizen_imaizumi/

サクッとリソースを作成したいような検証などでは、今回のようにAWSが提供しているクイックセットアップを利用するシーンが多々あるので、今後は注意したいと思います。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.